﻿using System.Diagnostics;

namespace FeishuWorkflowService.Services
{
    public class MemoryMonitorService : BackgroundService
    {
        private readonly ILogger<MemoryMonitorService> _logger;
        private readonly string _dumpFolder;
        private long _previousMemory = 0;
        private int _leakCounter = 0;
        private const long MEMORY_LEAK_THRESHOLD = 100 * 1024 * 1024; // 100MB
        private const int LEAK_COUNT_THRESHOLD = 5;

        public MemoryMonitorService(ILogger<MemoryMonitorService> logger)
        {
            _logger = logger;
            _dumpFolder = Path.Combine(AppContext.BaseDirectory, "MemoryDumps");
            if (!Directory.Exists(_dumpFolder))
                Directory.CreateDirectory(_dumpFolder);
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("内存监控服务已启动（基于dotnet-dump工具）");

            while (!stoppingToken.IsCancellationRequested)
            {
                MonitorMemory();
                await Task.Delay(30000, stoppingToken); // 每30秒检查一次
            }
        }

        private void MonitorMemory()
        {
            var process = Process.GetCurrentProcess();
            long currentMemory = process.WorkingSet64;
            _logger.LogInformation($"当前内存使用: {currentMemory / (1024 * 1024)} MB");

            // 检测内存泄露趋势
            if (_previousMemory > 0 && currentMemory - _previousMemory > MEMORY_LEAK_THRESHOLD)
            {
                _leakCounter++;
                _logger.LogWarning($"内存连续增长 {_leakCounter} 次，可能存在泄露风险");

                if (_leakCounter >= LEAK_COUNT_THRESHOLD)
                {
                    _logger.LogError("内存泄露风险达到阈值，生成内存快照");
                    GenerateDumpByTool("Leak");
                    _leakCounter = 0;
                }
            }
            else
            {
                _leakCounter = 0;
            }

            _previousMemory = currentMemory;
        }

        // 通过dotnet-dump工具生成内存快照（无NuGet包依赖）
        public void GenerateDumpByTool(string reason)
        {
            try
            {
                var dumpFileName = $"dump_{DateTime.Now:yyyyMMddHHmmss}_{reason}_{Process.GetCurrentProcess().Id}.dmp";
                var dumpFilePath = Path.Combine(_dumpFolder, dumpFileName);

                // 调用dotnet-dump命令行工具生成完整dump
                var process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "dotnet-dump",
                        Arguments = $"collect -o \"{dumpFilePath}\" -p {Process.GetCurrentProcess().Id} --type Full",
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        RedirectStandardError = true,
                        CreateNoWindow = true
                    }
                };

                process.Start();
                string output = process.StandardOutput.ReadToEnd();
                string error = process.StandardError.ReadToEnd();
                process.WaitForExit();

                if (process.ExitCode == 0)
                {
                    _logger.LogInformation($"内存快照已生成: {dumpFilePath}");
                    _logger.LogDebug($"dotnet-dump输出: {output}");
                }
                else
                {
                    _logger.LogError($"生成快照失败，错误码: {process.ExitCode}，错误信息: {error}");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "调用dotnet-dump工具时发生异常");
            }
        }
    }
}
